package cn.good.yan.service.t7;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicMarkableReference;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.atomic.AtomicStampedReference;

/**
 * 7. 原子类
 * 引用类型原子类：AtomicReference、AtomicStampedReference、AtomicMarkableReference
 * 原子性 - AtomicMarkableReference 它是通过状态，true、false 来判断值是否被更改
 * 原子性 - AtomicStampedReference 它是通过版本号，版本号可以+1，判断修改过几次
 *
 * @author shengren.yan
 * @create 2024-03-31
 */
public class AtomicDemo3 {

    // 原子类  该值是100, false:代表没有修改过
    static AtomicMarkableReference<Integer> markableReference = new AtomicMarkableReference(100, false);

    public static void main(String[] args) {
        new Thread(() -> {
            // 获取该值有没有被修改过，状态值：true、false
            boolean marked = markableReference.isMarked();
            System.out.println(Thread.currentThread().getName() + "\t" + "【t1线程】第一次获取：默认标识：" + marked);
            // 暂停1秒钟线程,等待后面的T2线程和我拿到一样的模式flag标识，都是false
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            // 比较并交换，把100 改为1000
            markableReference.compareAndSet(100, 1000, marked, !marked);
        }, "t1").start();

        new Thread(() -> {
            boolean marked = markableReference.isMarked();
            System.out.println(Thread.currentThread().getName() + "\t" + "【t2线程】第一次获取：默认标识：" + marked);
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            // 把100 改为2000
            boolean b = markableReference.compareAndSet(100, 2000, marked, !marked);
            // 改值失败，因为：t1线程已经更改成功，状态是 true，需要重新获取状态
            System.out.println(Thread.currentThread().getName() + "\t" + "t2线程，改值： " + b);
            System.out.println(Thread.currentThread().getName() + "\t" + markableReference.isMarked());
            System.out.println(Thread.currentThread().getName() + "\t" + markableReference.getReference());
        }, "t2").start();
    }

}
